package com.aspire.boc.mms.wmf.log;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import ognl.Ognl;
import ognl.OgnlException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.aspire.boc.mms.wmf.model.WmfOperateLog;
import com.aspire.boc.mms.wmf.service.OperateLogService;
import com.aspire.boc.mms.wmf.util.OperaLog;

/**
 * 系统日志类
 */
@Component
@Aspect
public class SystemLogAspect {
	private Log log = LogFactory.getLog(this.getClass());
	@Autowired
	OperateLogService operaLogService;
	
	@Transactional
	@Around("execution(public * com.aspire.boc.mms.wmf.action.*.*(..))")
	public Object insert(ProceedingJoinPoint pjp) throws Throwable {
		// 执行完方法的返回值：调用proceed()方法，就会触发切入点方法执行
		Object resVal = pjp.proceed();//执行的返回结果
		
		Method method = ((MethodSignature) pjp.getSignature()).getMethod();
		if (method.isAnnotationPresent(OperaLog.class)) {
			log.info("adviceResVal=" + resVal);
			if (Integer.parseInt(resVal.toString()) > 0) {
				OperaLog opera = method.getAnnotation(OperaLog.class);
				/*
				 *  被拦截参数
				 */
				Object[] bizArgs = pjp.getArgs();
				/* 
				 * 标注执行动作，操作对象，参数 
				 */
				String action = opera.action();
				String operaObj = opera.operaObj();
				String[] annoParameters = opera.parameters();
				/*
				 *  整理消息 
				 */
				String msg = this.getMessage(action, annoParameters, bizArgs);
				WmfOperateLog cmOpera = new WmfOperateLog();
				cmOpera.setUsername(String.valueOf(bizArgs[0])); 
				cmOpera.setOperObject(operaObj);
				cmOpera.setOperAction(msg);
				cmOpera.setTimestamp(new Date());
				operaLogService.insertOperateLog(cmOpera);
				log.info("save"+operaObj+msg+"Success...");
			}
		}
		return resVal;
	}


	/**
	 * 解析指定消息
	 */
	private String getMessage(String action, String[] annoParameters,
			Object[] bizArgs) {

		if (action == null)
			return null;
		/*
		 * 根据标注参数获取表达式参数表
		 */
		Map<String, Object> ognlContext = new HashMap<String, Object>();
		for (int i = 0; i < annoParameters.length; i++) {
			//标注参数不能大于实际参数
			Object paramValue = (i >= bizArgs.length) ? null : bizArgs[i];
			ognlContext.put(annoParameters[i], paramValue);
		}

		/*
		 *　整理表达式参数和值的映射集合
		 *  整理action匹配出对应值expressions
		 */
		Pattern pattern = Pattern.compile("\\$\\{(.+?)\\}");
		Matcher matcher = pattern.matcher(action);
		Map<String, Object> expressions = new HashMap<String, Object>();
		while (matcher.find()) {
			expressions.put(matcher.group(1), null);
		}

		Iterator<String> expIter = expressions.keySet().iterator();
		while (expIter.hasNext()) {
			String exp = expIter.next();
			Object expValue = null;
			try {
				expValue = Ognl.getValue(exp, ognlContext, ognlContext);
			} catch (OgnlException e) {
			}
			expressions.put(exp, expValue);
		}

		/*
		 * 替换action字符串
		 */
		expIter = expressions.keySet().iterator();
		String result = action;
		while (expIter.hasNext()) {
			String exp = expIter.next();
			Object expValue = expressions.get(exp);
			String replaceStr = null;
			if (expValue != null) {
				if (expValue.getClass().isArray()) {
					if (expValue.getClass().getComponentType() == boolean.class) {
						replaceStr = Arrays.toString((boolean[]) expValue);
					} else if (expValue.getClass().getComponentType() == byte.class) {
						replaceStr = Arrays.toString((byte[]) expValue);
					} else if (expValue.getClass().getComponentType() == char.class) {
						replaceStr = Arrays.toString((char[]) expValue);
					} else if (expValue.getClass().getComponentType() == double.class) {
						replaceStr = Arrays.toString((double[]) expValue);
					} else if (expValue.getClass().getComponentType() == float.class) {
						replaceStr = Arrays.toString((float[]) expValue);
					} else if (expValue.getClass().getComponentType() == int.class) {
						replaceStr = Arrays.toString((int[]) expValue);
					} else if (expValue.getClass().getComponentType() == long.class) {
						replaceStr = Arrays.toString((long[]) expValue);
					} else if (expValue.getClass().getComponentType() == short.class) {
						replaceStr = Arrays.toString((short[]) expValue);
					} else {
						replaceStr = Arrays.toString((Object[]) expValue);
					}
				} else {
					replaceStr = expValue.toString();
				}
			} else {
				replaceStr = "null";
			}
			result = result.replace("${" + exp + "}", replaceStr);
		}

		return result;
	}

}
